<?php
/**
 * @see Alinks_Cacher_Interface
 */
require_once('Alinks/Cacher/Interface.php');

/**
 * Cacher class that wraps WordPress's build in caching functions
 *
 * Copyright (C) 2008  Sean Hickey
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Sean Hickey <sean@headzoo.com>
 * @version $Id: Wordpress.php 387 2008-07-03 05:35:19Z sean $
 * @package Alinks_Cacher
 */
class Alinks_Cacher_Wordpress implements Alinks_Cacher_Interface
{
	/**
	 * Sets the caching options
	 *
	 * @param array $options The options
	 * @return Alinks_Cacher_Wordpress
	 */
	function setOptions(array $options)
	{
		return $this;
	}
	
	/**
	 * Returns the caching options
	 *
	 * @return array
	 */
	function getOptions()
	{
		return array();
	}
	
	/**
	 * Returns if cached content exists for the given key
	 *
	 * @param string $key The cache key
	 * @param string $namespace The cache namespace
	 * @return bool
	 */
	function exists($key, $namespace)
	{
		$key = $this->_clean($key);
		$namespace = 'alinks_' . $this->_clean($namespace);
		return (wp_cache_get($key, $namespace) !== false);
	}
	
	/**
	 * Sets content to be cached
	 *
	 * @param string $key The cache key
	 * @param string $namespace The cache namespace
	 * @param mixed $value The cache value
	 * @param int $expires Number of seconds to keep the value cached
	 * @return Alinks_Cacher_Wordpress
	 */
	function set($key, $namespace, $value, $expires = 0)
	{
		$key = $this->_clean($key);
		$namespace = 'alinks_' . $this->_clean($namespace);
		
		/**
		 * WordPress's wp_cache_get() function returns false when there
		 * is no cache available. That's a problem when trying to cache
		 * the boolean value false. So we won't. We'll cache something
		 * that represents false.
		 */
		if (false === $value) {
			$value = new stdClass();
			$value->__alinks_real_false = 1;
		}
		wp_cache_set($key, $value, $namespace, $expires);
		return $this;
	}
	
	/**
	 * Returns cached content
	 *
	 * Throws a Alinks_Cacher_Exception if no cache exists for the
	 * given key and namspace. Use exists() first to be sure the cached
	 * content exists.
	 *
	 * @param string $key The cache key
	 * @param string $namespace The cache namespace
	 * @return mixed
	 */
	function get($key, $namespace)
	{
		$key = $this->_clean($key);
		$namespace = 'alinks_' . $this->_clean($namespace);
		$value = wp_cache_get($key, $namespace);
		
		if (false === $value) {
			/**
			 * @see Alinks_Cacher_Exception
			 */
			require_once('Alinks/Cacher/Exception.php');
			throw new Alinks_Cacher_Exception("No cache exists for $key in namespace $namespace");
		}
		
		/**
		 * Check if the cached value is our own "special" false value.
		 * @see Alinks_Cacher_Wordpress::set()
		 */
		if ($value instanceof stdClass && isset($value->__alinks_real_false)) {
			$value = false;
		}
		
		return $value;
	}
	
	/**
	 * Deletes any cached content for the given key and namespace
	 *
	 * Returns true if the cache was deleted, false if not. False doesn't
	 * mean an error. It could just mean there was no cache to delete.
	 *
	 * @param string $key The cache key
	 * @param string $namespace The cache namepsace
	 * @return bool
	 */
	function delete($key, $namespace)
	{
		$key = $this->_clean($key);
		$namespace = 'alinks_' . $this->_clean($namespace);
		return wp_cache_delete($key, $namespace);
	}
	
	/**
	 * Flushes the cache
	 *
	 * Flushes the cache. If $namspace is specified, then only cached
	 * content within that namespace will be flushed.
	 *
	 * This method always returns true.
	 *
	 * @param string $namespace The cache namespace
	 * @return bool
	 */
	function flush($namespace = null)
	{
		wp_cache_flush();
		return true;
	}
	
	/**
	 * Removes any special characters from the string
	 *
	 * @param string $string The string
	 * @return string
	 */
	protected function _clean($string)
	{
		return preg_replace('/([^0-9A-Z_])/i', '_', $string);
	}
}